<?php
/*
	CView is the central class of the CView framework. CView allows the developer to
	write html pages in an object oriented way, very much like java's swing. This is possible
	through an object oriented abstraction layer that inherits from CView and CContainer
	to display templated html content in a recursive, tree-like arrangement.
	
	CView is easy to configure and use. Creating your own CView classes requires very little
	effort, and the aim is to stack a sufficient library of classes to create just about any web application
	thinkable.
	
	This is archieved through several concepts:
	
	-Every CView object can be viewed as a page. With a simple method call, you recieve a fully functional
	html page displaying the object in question, along with all of it's css and js dependencies.
	
	-Styles and Scripts dependencies are saved within object's state. This way, you never have to worry about
	what js or css files are needed, CView remembers this for you. By displaying a CView object, all of
	it's sub-components are displayed, and their css and js dependencies will be magically added at the top of the
	page.
	
	-Css and Js autoload. Cview subclasses will automatically load css and js files with it's own class name,
	meaning less configuration and more ease of use.
	
	-Easy CSS development. Independently develop css for every class, and later on compile a production css file,
	hassle free!
*/
class CView
{
// ---- CONFIG --- //
//Note, some configurations are not optional.
	public static $ROOT = "";								//Physical path to the website's static content root. (where css and js folders are located)
	public static $URL_ROOT = "";						//URL path to the website's root. (same as above, just the url version)
	
	public static $AUTOLOAD_CSS = true;			//Enable this to autoload class_name.css files inside cv_default folder.
																					//You may want to disable this feature during production stage for better performing pages.
																					
	public static $AUTOLOAD_JS = true;			//Same as above.
	
	public static $AUTOLOAD_CSS_DIR = "css/cv_default/";
	public static $AUTOLOAD_JS_DIR = "js/cv_default/";
	
	public $id = "";												//The Object's id attribute.
	public $css_class = "";									//Default is get_class($this)
	public $sub_class = "";									//Set extra css classes here (for style composition)
	public $css_options = array();					//assosiative array of object-specific css options.
	public $title = "";											//The html file header title.
	
	protected $stylesheets = array();				//Array of css files (already formated to html)
	protected $scripts = array();						//Array of js files (same as above)
	
	//Constructor:
	//Assigns a default title and autoloads both css and js files.
	public function __construct()
	{
		$this->title = get_class($this);
		$this->css_class = get_class($this);
		$css_file = self::$ROOT.self::$AUTOLOAD_CSS_DIR.get_class($this) . ".css";
		$css_default = self::$ROOT.self::$AUTOLOAD_CSS_DIR."default.css";
		if (self::$AUTOLOAD_CSS)
		{
			if (file_exists($css_file))
				$this->add_stylesheet('cv_default/' . get_class($this) . '.css');
			if (file_exists($css_default))
				$this->add_stylesheet('cv_default/default.css');
		}
			
		$js_file = self::$ROOT.self::$AUTOLOAD_JS_DIR.get_class($this) . ".js";
		if (file_exists($js_file))
			$this->add_script('cv_default/' . get_class($this) . '.js');
	}
	
	//Renders the object's <body>.
	public function __toString()
	{
		return $this->render();
	}
	
	//Renders an entire html page.
	public function htmldoc()
	{
		$r = "<!DOCTYPE html>\n<html>\n<head>\n	<title>$this->title</title>\n";
		foreach ($this->get_stylesheets() as $style)
		{
			$r .= $style;
		}
		foreach ($this->get_scripts() as $script)
		{
			$r .= $script;
		}
		$r .= "</head>\n<body>\n{$this->render()}\n</body>\n</html>";
		return $r;
	}
	
	//Renders the object's <body>
	public function render()
	{
		return '<div'.$this->print_class().$this->print_id().$this->print_options().'>'."\n".$this->render_contents().'</div>'."\n";
	}
	
	//Returns the view's contents in html format.
	protected function render_contents()
	{
		return get_class($this);
	}
	
	//Prints the object's id if it exists.
	protected function print_id()
	{
		if ($this->id != "")
			return ' id= "' . $this->id . '" ';
		else
			return "";
	}
	
	//Prints the object's class and sub classes.
	protected function print_class()
	{
		return ' class="'.$this->css_class.' '.$this->sub_class.'" ';
	}	
	
	protected function print_options()
	{
		if (count($this->css_options) == 0)
			return "";
		$r = 'style="';
		foreach ($this->css_options as $key => $value)
		{
			$r .= $key.': '.$value.'; ';
		}
		$r .= '"';
		return $r;
	}
	
	//Adds a css file or <style>
	public function add_stylesheet($stylesheet, $from_file = true)
	{
		if($from_file == true)
			$string = "	<link rel=\"stylesheet\" href=\"". self::$URL_ROOT . "css/$stylesheet\">\n";
		else
			$string = "	<style>\n$stylesheet\n	</style>\n";
		array_push($this->stylesheets, $string);
	}
	
	//Retrieves all the stylesheets (in html format)
	public function get_stylesheets()
	{
		return $this->stylesheets;
	}
	
	//Adds a js file of <script>
	public function add_script($script, $from_file = true)
	{
		if ($from_file)
			$string = "	<script type=\"text/javascript\" src=\"". self::$URL_ROOT . "js/$script\"></script>\n";
		else
			$string = "	<script type=\"text/javascript\">\n$script\n	</script>\n";
		array_push($this->scripts, $string);
	}
	
	//Retrieves all js references (in html format)
	public function get_scripts()
	{
		return $this->scripts;
	}
}

//EXCEPTIONS

class CViewException extends Exception
{
}

class CViewInvalidComponentException extends CViewException
{
}
?>